package top.lcm889.juc.threadsafe;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Coder-lcm
 * @date 2021/6/4
 */
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        int count = 1000;
        CountDownLatch latch = new CountDownLatch(count);
        UnSafeDemo test = new UnSafeDemo();
        UnSafeDemo test2 = new UnSafeDemo();
        UnSafeDemo test3 = new UnSafeDemo();
        UnSafeDemo test4 = new UnSafeDemo();
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 1000; i++) {
            executorService.execute(() -> {
                test.add();
                test2.addBySafe();
                test3.addBySync();
                test4.addSafeCount();
                latch.countDown();
            });
        }
        latch.await();
        executorService.shutdown();
        System.out.println(test.get());
        System.out.println(test2.get());
        System.out.println(test3.get());
        System.out.println(test4.getSafeCount());
    }
}
class UnSafeDemo{
    private int count;
    private ReentrantLock lock = new ReentrantLock();
    private AtomicInteger countSafe = new AtomicInteger();

    /**
     * 1. 非线程安全版
     */
    public void add(){
        System.out.println("非线程安全实现" + Thread.currentThread().getName() + " " + ++count);
    }

    /**
     * 2. 线程安全版自增：使用同步关键字保证
     */
    public synchronized void addBySync(){
        System.out.println("Sync: " + Thread.currentThread().getName() + " " + ++count);
    }

    /**
     * 3. 线程安全版自增：使用lock来保证线程安全
     */
    public void addBySafe(){
        lock.lock();
        try {
            System.out.println("Lock "+Thread.currentThread().getName() +" 加一操作" + ++count);
        }finally {
            lock.unlock();
        }

    }

    /**
     * 原子类保证操作原子性，进而保证线程安全
     */
    public void addSafeCount(){
        countSafe.incrementAndGet();
    }

    public int get(){
        return count;
    }

    public int getSafeCount(){
        return countSafe.get();
    }
}
